package net.tv90.mchrmixin.mixin;

import mcheli.MCH_Camera;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityFireball;
import net.minecraft.entity.projectile.EntityFishHook;
import net.minecraft.entity.projectile.EntitySnowball;
import org.lwjgl.opengl.GL11;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(value = RenderManager.class, remap = false)
public abstract class MixinRenderManager {

    @Unique
    private float mCH_Reforged_mixin$lastBrightnessX;
    @Unique
    private float mCH_Reforged_mixin$lastBrightnessY;
    @Unique
    private boolean mCH_Reforged_mixin$optifineBreak = false;

    @Inject(method = "func_147939_a",
        at = @At(value = "INVOKE",
            target = "Lnet/minecraft/client/renderer/entity/Render;func_76986_a(Lnet/minecraft/entity/Entity;DDDFF)V")
    )
    private void onDoRender(Entity entity, double x, double y, double z,
                            float yaw, float partialTicks, boolean flag,
                            CallbackInfoReturnable<Boolean> cir) {
        if (MCH_Camera.currentCameraMode == MCH_Camera.MODE_THERMALVISION) {
            if (mCH_Reforged_mixin$shouldApplyThermalVision(entity)) {
                GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
                GL11.glDisable(GL11.GL_TEXTURE_2D);
                GL11.glEnable(GL11.GL_BLEND);
                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
                GL11.glEnable(GL11.GL_ALPHA_TEST);
                GL11.glAlphaFunc(GL11.GL_GREATER, 0.1f);
                GL11.glDisable(GL11.GL_LIGHTING);
                GL11.glColor4f(1000f, 0f, 1000f, 1.0f);
                mCH_Reforged_mixin$glowOn(15);
            }
        }
    }

    @Inject(method = "func_147939_a",
        at = @At(value = "INVOKE",
            target = "Lnet/minecraft/client/renderer/entity/Render;func_76986_a(Lnet/minecraft/entity/Entity;DDDFF)V",
            shift = At.Shift.AFTER)
    )
    private void afterDoRender(Entity entity, double x, double y, double z,
                               float yaw, float partialTicks, boolean flag,
                               CallbackInfoReturnable<Boolean> cir) {
        if (MCH_Camera.currentCameraMode == MCH_Camera.MODE_THERMALVISION) {
            if (mCH_Reforged_mixin$shouldApplyThermalVision(entity)) {
                mCH_Reforged_mixin$glowOff();
                GL11.glPopAttrib();
                GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
                GL11.glEnable(GL11.GL_LIGHTING);
                GL11.glEnable(GL11.GL_TEXTURE_2D);
            }
        }
    }

    @Unique
    private boolean mCH_Reforged_mixin$shouldApplyThermalVision(Entity entity) {
        return !(entity instanceof EntityItem) &&
            !(entity instanceof EntityArrow) &&
            !(entity instanceof EntityXPOrb) &&
            !(entity instanceof EntityFishHook) &&
            !(entity instanceof EntitySnowball) &&
            !(entity instanceof EntityFireball);
    }

    @Unique
    private void mCH_Reforged_mixin$glowOn(int glow) {
        GL11.glPushAttrib(GL11.GL_LIGHTING_BIT);
        try {
            mCH_Reforged_mixin$lastBrightnessX = OpenGlHelper.lastBrightnessX;
            mCH_Reforged_mixin$lastBrightnessY = OpenGlHelper.lastBrightnessY;
        } catch (NoSuchFieldError e) {
            mCH_Reforged_mixin$optifineBreak = true;
        }
        float glowRatioX = Math.min((glow / 15F) * 240F + mCH_Reforged_mixin$lastBrightnessX, 240);
        float glowRatioY = Math.min((glow / 15F) * 240F + mCH_Reforged_mixin$lastBrightnessY, 240);
        if (!mCH_Reforged_mixin$optifineBreak) {
            OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, glowRatioX, glowRatioY);
        }
    }

    @Unique
    private void mCH_Reforged_mixin$glowOff() {
        if (!mCH_Reforged_mixin$optifineBreak) {
            OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit,
                mCH_Reforged_mixin$lastBrightnessX, mCH_Reforged_mixin$lastBrightnessY);
        }
        GL11.glPopAttrib();
    }
}
